/*
 * BIT READER
 * Streams over bits held as byte data in memory.
 * Word-based is faster but offers endianness complexities,
 * so this is char-based.
 */

#include "bitreader.h"

struct _KewBitReader {
    unsigned mask; /*  starts on Most Significant Bit */
    unsigned index;
    unsigned size_in_bytes;
    gchar *data;
};

KewBitReader *kew_bit_reader_new(gchar *data, unsigned size_in_bytes)
{
    KewBitReader bit_stream = kew_new(KewBitReader);
    bit_stream->data = data;
    bit_stream->size_in_bytes = size_in_bytes;
    bit_stream->index = 0;
    bit_stream->mask = 0x80;
    return bit_stream;
}

/* FIXME: I think this may be unused */
void kew_bit_reader_align_byte(KewBitReader *bit_reader)
{
    if (bit_reader->mask != 0x80) {
        bit_reader->mask = 0x80;
        ++(bit_reader->index);
    }
}

gboolean kew_bit_reader_empty(KewBitReader *bit_stream)
{
    return (! bit_stream->mask) && (bit_stream->index == bit_stream->size_in_bytes);
}

unsigned kew_bit_reader_read(KewBitReader *bit_stream)
{
    unsigned bit;
    
    if (! bit_stream->mask) {
        ++(bit_stream->index);
        bit_stream->mask = 0x80;
    }
    
    bit = bit_stream->data[bit_stream->index] & bit_stream->mask;
    bit_stream->mask >>= 1;
    return bit ? 1 : 0;
}

unsigned kew_bit_reader_read_n(KewBitReader *bit_stream, unsigned bits_to_read)
{
    unsigned bit;
    unsigned result;
    for (bit = 0; bit < bits_to_read; ++bit) {
        result |= kew_bit_reader_read(bit_stream);
        result <<= bits;
    }
    return result;
}
